from pml import Objects
from pml.Eval import frame as Frame
from pml.Eval import Runner

class PMFunctionObject(Objects.object.typeobject):
    def __init__(self, frame: Frame.Frame | None = None, name='', *args):
        super().__init__('function')
        self.name = name
        self.args = args
        self.frame = frame
    def __repr__(self):
        return f'<Function  {self.name}>'

    def getObject(self):
        self.methods['__init__'] = self.tp_init
        self.methods['__print__'] = self.tp_print

        self.methods['__call__'] = self.tp_call

        return self

    @staticmethod
    def tp_init(frame, this, position):
        pass

    @staticmethod
    def tp_print(frame, this, position):
        return Objects.object.PMTypeObject(Objects.PMStringObject.PMStringObject(this.__repr__()).getObject())

    @staticmethod
    def tp_call(frame, this: 'PMFunctionObject', position, self, *args):
        args = list(args)
        if this.args.__len__() < args.__len__():
            raise TypeError
        for i in range(this.args.__len__() - args.__len__()):
            args.append(Objects.object.PMTypeObject(Objects.PMNullObject.PMNullObject().getObject()))

        variable = {}
        for i in range(args.__len__()):
            variable[this.args[i]] = args[i]
        variable['this'] = self.methods

        runFrame = this.frame.copy(frame, this.frame, position=None).obj
        runFrame.variable = variable

        runner = Runner.Runner(runFrame, begin=False, this=self, position=position)

        return runner.error, runner.run(runFrame, runner, position=position), runner.errorFrame
